// LookupNamespaceItemWindow.cs
//
// Author:
//   Mike Krüger <mkrueger@novell.com>
//
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Collections.Generic;

using Gtk;

using MonoDevelop.Ide.Gui;
using MonoDevelop.Core;
using MonoDevelop.Projects.Dom;
using MonoDevelop.Projects.Dom.Output;
using MonoDevelop.Projects.Dom.Parser;
using MonoDevelop.Components;
using MonoDevelop.SourceEditor;

namespace MonoDevelop
{
	public class LookupNamespaceItemWindow: MonoDevelop.Components.TooltipWindow
	{		
		
		static string declareUsingStr = GettextCatalog.GetString ("Declare using");		
		private IList<string> _Namespaces;
		private ExtensibleTextEditor _Editor;
		public bool IsEmpty {
			get; 
			set;
		}
		
		
		static string GetNamespaceNames (IList<string> namespaces)
		{
			if(namespaces == null)
			{
				return string.Empty;
			}
			StringBuilder stringBuilder = new StringBuilder();
			for(int counter = 0; counter < namespaces.Count - 1; counter++)
			{
				stringBuilder.AppendLine(String.Format("{0} {1}", declareUsingStr, namespaces[counter]));
			}
			if(namespaces.Count > 0)
			{
				stringBuilder.Append(String.Format("{0} {1}", declareUsingStr, namespaces[namespaces.Count - 1]));
			}
		
			return stringBuilder.ToString();
		}
		
		public LookupNamespaceItemWindow (ProjectDom dom, Ambience ambience, IList<string> types, ICompilationUnit unit, ExtensibleTextEditor editor)
		{			
			
			// Approximate value for usual case
			StringBuilder s = new StringBuilder(150);
			string doc = null;
			if (types != null) {					
				s.Append (GetNamespaceNames (types));
			}
			_Namespaces = types;
			_Editor = editor;
			
			if (s.ToString ().Trim ().Length == 0) {
				IsEmpty = true;
				return;
			}
			
			MonoDevelop.Components.FixedWidthWrapLabel lab = new MonoDevelop.Components.FixedWidthWrapLabel ();			
			lab.Indent = -20;
			lab.BreakOnCamelCasing = true;
			lab.BreakOnPunctuation = true;
			lab.Markup = s.ToString ();
			this.BorderWidth = 3;			
			Add (lab);			
			this.ButtonPressEvent += LabelClick;
			this.Events = Gdk.EventMask.ButtonPressMask;
			EnableTransparencyControl = true;			
		}
		
		private void LabelClick(object o, ButtonPressEventArgs args)
		{
			Gtk.Widget lab = (Gtk.Widget)o;
			Requisition size = lab.SizeRequest();
			string namespaceName = _Namespaces[(int)((double)args.Event.Y / ((double)size.Height / (double)_Namespaces.Count))];
			Mono.TextEditor.Document document = _Editor.Document;
			Regex regex = new Regex("^using +[abcdeghijklmnopqrstuvwxyz1234567890.]+ *;$", RegexOptions.IgnoreCase | RegexOptions.Multiline);			
			MatchCollection matchCollection = regex.Matches(document.Text);
			int endOfLastUsing = 0;
			if(matchCollection.Count > 0)
			{
				string lastUsing = "";
				foreach(Match match in matchCollection)
				{
					lastUsing = match.Value;
				}
				endOfLastUsing = document.Text.IndexOf(lastUsing) + lastUsing.Length;				
			}
			//Atomic undo doesn't seem to work
			//document.BeginAtomicUndo();
			document.Text = document.Text.Insert(endOfLastUsing, String.Format("{0}using {1};", Environment.NewLine, namespaceName));
			int lineNumber = document.OffsetToLineNumber(endOfLastUsing);
			document.CommitMultipleLineUpdate(lineNumber, lineNumber+1);						
			//document.EndAtomicUndo();
			this.Visible = false;
		}
			                                              
		//return the real width
		public int SetMaxWidth (int maxWidth)
		{
			MonoDevelop.Components.FixedWidthWrapLabel l = (MonoDevelop.Components.FixedWidthWrapLabel)Child;
			l.MaxWidth = maxWidth;
			return l.RealWidth;
		}
	}
}
